package arena.tools;


import ronin.graphics.*;
import ronin.scene.*;
import ronin.util.MessageDispatcher;
import ronin.actor2d.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import java.applet.Applet;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Vector;

public class ArenaEditor extends GrimaceGamelet implements ItemListener {
	
	public final int INFO_FLOOR = 1;
	public final int INFO_OBSTACLE = 11;
	public final int INFO_SPAWN = 111;
	
	// main panels.
	Panel menuBar, statusBar, infoBar;
	
	CheckboxGroup floorChoiceGroup, obstacleChoiceGroup, panelChoiceGroup, spawnChoiceGroup;
	Checkbox[] floorChoices, obstacleChoices, spawnChoices;
	
	Checkbox floorButton, obstacleButton, spawnButton;
	
	int currentInfoPanel;
	
	// sub panels
	Panel backgroundPanel, obstaclePanel, spawnPanel, arenaInfoPanel;
	
	Label statusLabel, timeLabel;
	Rectangle2D arenaBounds;
	
	String[] floorTypes = {"Grass",
						   "Woodboards",
						   "Pinewood",
						   "Concrete",
						   "Stone",
						   "Dirt",
						   "Greens"};
	
	String[] obstacleTypes = {"obstacle", 
			                  "obstacle2", 
			                  /*"Wall", 
			                  "Crate", 
			                  "Box", 
			                  "Car", 
			                  "Truck", 
			                  "Van",
			                  "Policecar",
			                  "Wreck",
			                  "Barrel", 
			                  "Barricade", 
			                  "Sandbag"*/};
	
	String[] spawnTypes = {"Player", "Enemy", "Item"};
	
	StaticActor[] obstacles;
	StaticActorGroup[] obstacleGroups; 
	StaticActorGroup[] spawnGroups;
	
	ArenaScene sceneManager;

	
	public ArenaEditor(){
		super(950, 600, true);
		out(System.getProperty("codebase"));
		
		arenaBounds = new Rectangle2D.Double(0.0, 0.0, 800.0, 600.0);
		
		
		// initialize obstacle groups and obstacles based on type array. 
		//loadObstacles();
		setLayout(new BorderLayout());
		menuBar = new Panel();
		statusBar = new Panel();
		infoBar = new Panel();
		infoBar.setLayout(new GridLayout(4, 1));
		backgroundPanel = new Panel(); 
		backgroundPanel.setLayout(new GridLayout(7, 1));
		obstaclePanel = new Panel();
		obstaclePanel.setLayout(new GridLayout(obstacleTypes.length, 1));
		spawnPanel = new Panel();
		spawnPanel.setLayout(new GridLayout(spawnTypes.length, 1));
		arenaInfoPanel = new Panel();
				
		statusBar.setLayout(new BorderLayout());
		
		statusLabel = new Label("Status Info goes here");
		timeLabel = new Label("Time in minutes and seconds.");
		
		// setup menu bar items and menubar.
		panelChoiceGroup = new CheckboxGroup();
		obstacleButton = new Checkbox("Obstacles", panelChoiceGroup, false);
		floorButton = new Checkbox("Arena Floor", panelChoiceGroup, false);
		spawnButton = new Checkbox("Spawners", panelChoiceGroup, false);
		obstacleButton.addItemListener(this);
		floorButton.addItemListener(this);
		spawnButton.addItemListener(this);
		
		
		menuBar.add(new Label("Choose Panel:  "));
		menuBar.add(obstacleButton);
		menuBar.add(floorButton);
		menuBar.add(spawnButton);
		
		// setup background panel
		floorChoiceGroup = new CheckboxGroup();
		floorChoices = new Checkbox[floorTypes.length];
		int i  = 0;
		for(final String choice: floorTypes){
			floorChoices[i] = new Checkbox(choice, floorChoiceGroup, false);
			backgroundPanel.add(floorChoices[i]);
		
			i++;
		}
		//backgroundPanel.setVisible(false);
		
		// setup obstacle panel
		obstacleChoiceGroup = new CheckboxGroup();
		obstacleChoices = new Checkbox[obstacleTypes.length];
		i = 0;
		for(final String choice: obstacleTypes){
			obstacleChoices[i] = new Checkbox(choice, obstacleChoiceGroup, false);
			obstaclePanel.add(obstacleChoices[i]);
			i++;
		}
		//obstaclePanel.setVisible(false);
		
		spawnChoiceGroup = new CheckboxGroup();
		spawnChoices = new Checkbox[spawnTypes.length];
		i = 0;
		for(final String choice: spawnTypes){
			spawnChoices[i] = new Checkbox(choice, spawnChoiceGroup, false);
			spawnPanel.add(spawnChoices[i]);
			i++;
		}
		//spawnPanel.setVisible(false);
		
		infoBar.add(obstaclePanel);
		infoBar.add(backgroundPanel);
		infoBar.add(spawnPanel);
		
		
		
		// setup status bar
		statusBar.add(timeLabel, BorderLayout.EAST);
		statusBar.add(statusLabel, BorderLayout.WEST);
		
		// add main panels to the window
		add(infoBar, BorderLayout.EAST);
		add(menuBar, BorderLayout.NORTH);
		add(statusBar, BorderLayout.SOUTH);
		showInfoPanel(INFO_SPAWN);
	}
	
	public void itemStateChanged(final ItemEvent e){
		
		// make sure correct panel is shown
		if(panelChoiceGroup.getSelectedCheckbox().equals(floorButton)){
			currentInfoPanel = INFO_FLOOR;
			showInfoPanel(currentInfoPanel);
		}
		
		if(panelChoiceGroup.getSelectedCheckbox().equals(obstacleButton)){
			currentInfoPanel = INFO_OBSTACLE;
			showInfoPanel(currentInfoPanel);
		}
		
		if(panelChoiceGroup.getSelectedCheckbox().equals(spawnButton)){
			currentInfoPanel = INFO_SPAWN;
			showInfoPanel(currentInfoPanel);
		}
		// handle new choice selection based on the selected panel. 
		else{ out("NO SELECTION"); }
	}	
	
	
	public void processPlayerInput(){
		String infoPanelSelection;
		
		if(mouseClicked){
			if(button1Pressed){
				if(currentInfoPanel == INFO_SPAWN){
					// get current spawn panel selection.
					infoPanelSelection = spawnChoiceGroup.getSelectedCheckbox().getLabel();
					sceneManager.add(new StaticActor(spawnGroups[getIndex(infoPanelSelection, spawnTypes)]), QuadScene.UNIT_TYPE_DOOR);
				}
				if(currentInfoPanel == INFO_OBSTACLE){
					infoPanelSelection = obstacleChoiceGroup.getSelectedCheckbox().getLabel();
					sceneManager.add(new StaticActor(obstacleGroups[getIndex(infoPanelSelection, obstacleTypes)]), QuadScene.UNIT_TYPE_OBSTACLE);
				}
				if(currentInfoPanel == INFO_FLOOR){
					sceneManager.setFloor("images/floor/" + floorChoiceGroup.getSelectedCheckbox().getLabel() + ".png");
				}
			}
			
			if(button2Pressed){
				
			}
			
			if(button3Pressed){
				
			}
		}
	}
	/**
	 * Searched the string array for the given string and returns the index. If 
	 * the string is not found 1000000 is returned. 
	 * 
	 * Note string arrays exceeding this value will have to overide this function. 
	 * 1000000 is the max array size this function can work on. 
	 * 
	 * @param stringToFind string we are looking for.
	 * @param stringArrayToSearch the String Array we wish to search for the given string.
	 * @return index of the String if its found in the array or returns 1000000;
	 */
	public int getIndex(final String stringToFind, final String[] stringArrayToSearch){
		int i;
		int index = 1000000;
		
		for(i=0; i<stringArrayToSearch.length; i++){
			if(stringArrayToSearch[i] == stringToFind)
				index = i;
		}
		
		return index;
	}
	
	public void hideInfoPanels(){
		obstaclePanel.setVisible(false);
		spawnPanel.setVisible(false);
		backgroundPanel.setVisible(false);
	}
	
	public void showInfoPanel(final int infoPanelSelector){
		hideInfoPanels();
		
		switch(infoPanelSelector){
			case INFO_FLOOR:
				backgroundPanel.setVisible(true); 
				break;
			case INFO_OBSTACLE: 
				obstaclePanel.setVisible(true); 
				break;
			case INFO_SPAWN: 
				spawnPanel.setVisible(true); 
				break;
			default: out("Unable to Find the Panel Requested."); break;
		}
		infoBar.doLayout();
		infoBar.show();
		
	}
	
	public void loadObstacles(){
		final StaticActor[] obstacleArray = new StaticActor[obstacleTypes.length];
		
		int index = 0;
		// for each obstacle type
		for(final String type: obstacleTypes){
			obstacleGroups[index] = new StaticActorGroup(type + ".png");
			obstacleGroups[index].init(this);
			
			// create new obstacle from the group at correct index
			obstacles[index] = new StaticActor(obstacleGroups[index]);
			
			// move on to next obstacle
			index++;
		}
		// init the group
	}
	
	
	public boolean initializeObjectGroups(){
		
		int i = 0;
		obstacleGroups = new StaticActorGroup[obstacleTypes.length];
		
		for(final String filename: obstacleTypes){
			obstacleGroups[i] = new StaticActorGroup("images/obstacles/" + filename + ".png");
			obstacleGroups[i].init(this);
			i++;
		}
		
		i = 0;
		spawnGroups = new StaticActorGroup[spawnTypes.length];
		
		for(final String filename: spawnTypes){
			spawnGroups[i] = new StaticActorGroup("images/spawn/" + filename + ".png");
			spawnGroups[i].init(this);
			i++;
		}
		
		return true;
	}
	
	
	public void setupGame(){
		this.sceneManager = new ArenaScene(this, arenaBounds);
		this.sceneManager.setFloor("images/floor/" + floorTypes[0] + ".png");
		
		
		if(!initializeObjectGroups()){
			out("Unable to Initialize the Object Groups Array for some reason.");
			System.exit(0);
		}
		
		gameletStarted = true;
	}
	
	public void runGame()
	{
		this.sceneManager.update();
		timeLabel.setText(getTimeAsString());
	}
	
	public void paintScene(final Graphics2D g){
		g.setPaint(Color.BLACK);
		g.fill(arenaBounds);
		
		this.sceneManager.paint(g);
	
	}
	
	public String getTimeAsString(){
		Double seconds, minutes;
		
		final long currentTime = GrimaceGamelet.getMainApplet().getTimeElapsedInSeconds();
		minutes = new Double((double) currentTime/60);
		seconds = new Double((double) currentTime%60);
		
		return  new String(minutes.intValue() + "m " + seconds.intValue() + "s ");
	}
	public static void main(final String args[]) {	
	    final String appletName = "Arena Editor";
		final Frame appletFrame = new Frame(appletName);
		
		final WindowListener l = new WindowAdapter() {
		    public void windowClosing(WindowEvent e) {
			System.exit(0);
		    }
		};
		appletFrame.addWindowListener(l);
		appletFrame.setLayout(new GridLayout(1, 0));
		appletFrame.setSize(300, 300);
		appletFrame.setVisible(true);
		
		
		final Applet myApplet = new ArenaEditor();
		// Add the applet to the frame
		appletFrame.add(myApplet);
		
		// Now try to get an applet stub for this class.
		final RunAppletStub stub = new RunAppletStub(appletFrame, myApplet,
			"RoNinEnGine " + appletName, "/C:/Users/R/workspace/RoninEngine/bin/arena/tools/");
		myApplet.setStub(stub);
		// Initialize and start the applet
		myApplet.init();
		myApplet.start();
    }
}

class ArenaScene extends QuadScene{
	
	String floorImageFilename;
	BufferedImage floorImage;
	Applet app;
	
	ArenaScene(Applet a, Rectangle2D bounds){
		super(a, 4, bounds, bounds, true);
		this.app = a;
	}
	
	public void setFloor(String filename){
		floorImageFilename = filename;
		ImageLoader loader = new ImageLoader(this.app, floorImageFilename, true);
		floorImage = loader.getImage();
	}
	
	public void paint(Graphics2D g){
		Rectangle2D rect = new Rectangle2D.Double(0, 0,this.floorImage.getWidth(), 
				this.floorImage.getHeight());
		TexturePaint tp = new TexturePaint (this.floorImage, rect);

		g.setPaint(tp);
		g.fill(bounds);
		
		//g.drawImage(floorImage, 0, 0, this.mainApp);
		super.paint(g);	
	}
	
	
}